package com.platform.utils;

import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.platform.entity.WxTradeDetail;
import com.platform.entity.WxTradeSummary;
import com.platform.utils.excel.ExcelExport;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

public class WeChatUtils {

    private static Log logger = LogFactory.getLog(WeChatUtils.class);
    /**
     * 下载对账单
     */
    public static List<String> downloadFile() throws Exception {
        ArrayList<String> outList = new ArrayList<>();
//        String billDate = "20191217";
        String billDate = DateUtil.getYesterday("yyyyMMdd");
        //签名
        Map<Object, Object> parame = new TreeMap<>();

        parame.put("appid", ResourceUtil.getConfigByName("wx.appId"));                    // 商户号 app_id
        parame.put("mch_id", ResourceUtil.getConfigByName("wx.mchId"));                    // 应用ID mch_id
        parame.put("nonce_str", CharUtil.getRandomString(16));// 随机字符串 nonce_str
        //parame.put("tar_type", "GZIP");//非必传参数，固定值：GZIP，返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
        // ALL（默认值）  SUCCESS，返回当日成功支付的订单（不含充值退款订单） REFUND，返回当日退款订单（不含充值退款订单） RECHARGE_REFUND，返回当日充值退款订单
        parame.put("bill_type", "ALL");
        parame.put("bill_date", billDate);        // 下载对账单的日期，格式：20140603

        String sign = WeChatUtils.arraySign(parame, ResourceUtil.getConfigByName("wx.paySignKey"));

        // 数字签证
        parame.put("sign", sign);

        String xml = MapUtils.convertMap2Xml(parame);
        logger.info("xml:" + xml);
        // 获取下载信息
        String billUrl = ResourceUtil.getConfigByName("wx.downloadBillUrl");
        // 获取下载信息
        String result = HttpUtils.doPost(billUrl, xml);
        if (StringUtils.hasText(result) && !result.contains("error_code")) {

            // 全部订单的数据
            List<WxTradeDetail> wxTradeDetailList = new ArrayList<WxTradeDetail>();
            // 下载指定日期的所有订单统计
            WxTradeSummary wxTradeSummary = new WxTradeSummary();

            String[] str = result.split("\n");//按行读取数据（*这个尤为重要*）
            int len = str.length;
            for (int i = 0; i < len; i++) {
                String[] tradeDetailArray = str[i].replace("`", "").split(",");
                if (i > 0 && i < (len - 2)) {
                    // 明细行数据[交易时间,公众账号ID,商户号,特约商户号,设备号,微信订单号,商户订单号,用户标识,交易类型,交易状态,付款银行,货币种类,应结订单金额,代金券金额,商品名称,商户数据包,手续费,费率,订单金额,费率备注]
                    WxTradeDetail entity = new WxTradeDetail();
                    entity.setBillDate(billDate);
                    entity.setTransDate(getArrayValue(tradeDetailArray, 0));// 交易时间
                    entity.setCommonId(getArrayValue(tradeDetailArray, 1));// 公众账号ID
                    entity.setBusinessNo(getArrayValue(tradeDetailArray, 2));// 商户号
                    entity.setChildBusinessNo(getArrayValue(tradeDetailArray, 3));// 特约商户号
                    entity.setEquipmentNo(getArrayValue(tradeDetailArray, 4));// 设备号
                    entity.setWxOrderNo(getArrayValue(tradeDetailArray, 5));// 微信订单号
                    entity.setBusinessOrderNo(getArrayValue(tradeDetailArray, 6));// 商户订单号
                    entity.setUserIdentity(getArrayValue(tradeDetailArray, 7));// 用户标识
                    entity.setTransType(getArrayValue(tradeDetailArray, 8));// 交易类型
                    entity.setTransStatus(getArrayValue(tradeDetailArray, 9));// 交易状态
                    entity.setPaymentBank(getArrayValue(tradeDetailArray, 10));// 付款银行
                    entity.setCurrency(getArrayValue(tradeDetailArray, 11)); // 货币种类
                    entity.setSettleAccounts(getArrayValue(tradeDetailArray, 12)); // 应结订单金额
                    entity.setCoupon(getArrayValue(tradeDetailArray, 13)); // 代金券金额
                    entity.setBusinessName(getArrayValue(tradeDetailArray, 14));// 商品名称
                    entity.setBusinessData(getArrayValue(tradeDetailArray, 15));// 商户数据包
                    entity.setFee(getArrayValue(tradeDetailArray, 16));// 手续费
                    entity.setRate(getArrayValue(tradeDetailArray, 17));// 费率
                    entity.setOrderAmount(getArrayValue(tradeDetailArray, 18));// 订单金额
                    entity.setRateRemark(getArrayValue(tradeDetailArray, 19));// 费率备注
                    wxTradeDetailList.add(entity);
                    outList.add(getArrayValue(tradeDetailArray, 6) + "%"
                            + getArrayValue(tradeDetailArray, 7)
                            + getArrayValue(tradeDetailArray, 12)
                    );

                }
                // 汇总行数据 [总交易单数,应结订单总金额,退款总金额,充值券退款总金额,手续费总金额,订单总金额,申请退款总金额]
                if (i > (len - 2)) {
                    wxTradeSummary.setBillDate(billDate);
                    wxTradeSummary.setTradeCount(getArrayValue(tradeDetailArray, 0));// 总交易单数
                    wxTradeSummary.setShouldSettleAmount(getArrayValue(tradeDetailArray, 1));// 应结订单总金额
                    wxTradeSummary.setRefundAmount(getArrayValue(tradeDetailArray, 2));// 退款总金额
                    wxTradeSummary.setRechargeVoucherAmount(getArrayValue(tradeDetailArray, 3));// 充值券退款总金额
                    wxTradeSummary.setServiceCharge(getArrayValue(tradeDetailArray, 4));// 手续费总金额
                    wxTradeSummary.setTotalOrderAmount(getArrayValue(tradeDetailArray, 5));// 订单总金额
                    wxTradeSummary.setApplyRefundAmount(getArrayValue(tradeDetailArray, 6));// 申请退款总金额
                }
            }
        } else {
            System.out.println("###########获取对账数据有误#################");
            System.out.println("返回对账数据为:" + result);
        }
        return outList;

    }


    public static String getArrayValue(String[] tradeDetailArray, int index) {
        try {
            return tradeDetailArray[index];
        } catch (Exception e) {
            return "";
        }
    }

    public static Map<String, List<String>> contrast(List<String> innerOrderList) {
        HashMap<String, List<String>> map = new HashMap<>();
        List<String> successOrderList = new ArrayList<>();
        List<String> errorOrderList = new ArrayList<>();
        List<String> outOrderList = null;
        try {
            outOrderList = downloadFile();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (outOrderList != null && outOrderList.size() > 0) {
            int num = innerOrderList.size();

            ArrayList<String> list1 = new ArrayList<>();
            ArrayList<String> list2 = new ArrayList<>();
            list1.addAll(innerOrderList);
            list2.addAll(innerOrderList);

            list1.retainAll(outOrderList);
            if (list1.size() > 0) {
                for (String s : list1) {
                    String[] split = s.split("%");
                    successOrderList.add(split[0]);
                }
            }
            list2.removeAll(outOrderList);
            if (list2.size() > 0) {
                for (String s : list2) {
                    String[] split = s.split("%");
                    errorOrderList.add(split[0]);
                }
            }
        }
        map.put("successOrderList", successOrderList);
        map.put("errorOrderList", errorOrderList);
        return map;
    }

    /**
     * 方法描述：根据签名加密请求参数
     * 创建时间：2017年6月8日  上午11:28:52
     * 作者： xubo
     *
     * @param
     * @return
     */
    public static String arraySign(Map<Object, Object> params, String paySignKey) {
        boolean encode = false;
        Set<Object> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuffer temp = new StringBuffer();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = value.toString();
            }
            if (encode) {
                try {
                    temp.append(URLEncoder.encode(valueString, "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            } else {
                temp.append(valueString);
            }
        }
        temp.append("&key=");
        temp.append(paySignKey);
        System.out.println(temp.toString());
        String packageSign = MD5.getMessageDigest(temp.toString());
        return packageSign;
    }
}
